PrivateFunction Velocity ( _ ByVal latitude AsSingle, _ ByVal longitude AsSingle, _ ByVal elevation AsSingle _ ) AsSingle 'Preconditions Debug.Assert(-90 <= latitude And latitude <= 90) Debug.Assert(0 <= longitude And longitude < 360) Debug.Assert(-500 <= elevation And elevation <= 75000)
'Postconditions Debug.Assert( 0 <= returnVelocity And returnVelocity <= 600 ) 'return value Velocity = returnVelocity EndFunction
对于高健壮性的代码,应该先使用断言再处理错误
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
PrivateFunction Velocity ( _ ) AsSingle ' Preconditions Debug.Assert(-90 <= latitude And latitude <= 90) Debug.Assert(0 <= longitude And longitude < 360) Debug.Assert(-500 <= elevation And elevation <= 75000)
If (latitude < -90) Then latitude = -90 ElseIf (latitude > 90) Then latitude = 90 EndIf If (longitude < 0) Then longitude = 0 ElseIf (longitude > 360) Then ...
2.4.7. 前置条件
不要断言方法的规范
1 2 3 4 5 6 7 8 9 10 11 12
/** * Sets the refresh rate. * @param rate refresh rate, in frames per second. * @throws IllegalArgumentException if rate <= 0 or * rate > MAX_REFRESH_RATE. */ publicvoidsetRefreshRate(int rate){ // Enforce specified precondition in public method if (rate <= 0 || rate > MAX_REFRESH_RATE) thrownewIllegalArgumentException("Illegal rate: " + rate); setRefreshInterval(1000/rate); }
可以断言非public方法的前置条件
1 2 3 4 5 6 7 8 9 10
/** * Sets the refresh interval (to a legal frame rate). * @param interval refresh interval in milliseconds. */ privatevoidsetRefreshInterval( int interval ) { // preconditions in nonpublic method assert interval > 0 && interval <= 1000/MAX_REFRESH_RATE : interval; ... // Set the refresh interval }
2.4.8. 不变式Invariants
永远都应该为真的条件
内部不变式
程序运行到特定时刻应该为真的事实
如:assert x > 0
控制流不变式
断言不会被运行到的代码,如assert false: suit;
注意:将语句放置在编译器认为不会被运行到的地方会报错
类不变式
指类对象作为有效的类成员必须满足的条件
如:assert person.age >= 0 && person.age < 150;
在即将从public方法和构造函数中返回时断言类的不变式
2.4.9. 注意
断言是提高软件质量技术的有益辅助手段
可看作是可执行的注解
相比注释,能更主动地对程序中的假定作出说明
不能依赖断言来让代码正常工作:最佳方式是在一开始不要在代码中引入错误
断言不能有任何副作用
1 2 3
inti= pullNumberFromThinAir(); assert(i = 6); //错误的断言导致i被赋值 printf("i is 8d\n",i);
2.4.10. Question: 应该进行多少约束校验?
每一行都设置一个校验?过多的约束校验,可能使得代码的逻辑变得不明确
可读性是衡量程序质量的最佳标准
在主要函数中放置前置条件和后置条件,并且在关键的循环中放置不变条件,就已经足够了
在修正错误的地方加入一条断言也是一个良好的习惯
2.4.11. 补充:断言举例
1 2 3 4 5 6 7 8 9 10
publicclassAssertionDemo { publicstaticvoidmain(String[] args) { int i; intsum=0; for (i = 0; i < 10; i++) { sum += i; } assert i == 10; assert sum > 10 && sum < 5 * 10 : "sum is " + sum; } }
try { statement1; //Suppose no exceptions in the statements statement2; //Suppose an exception of type Exception1 is thrown in statement2 statement3; } catch(Exception1 ex) { handling ex; // The exception is handled. } catch(Exception2 ex){ handling ex; // Handling exception throw ex; // Rethrow the exception and control is transferred to the caller } finally { finalStatements; // The final block is always executed } Next statement;// Next statement in the method is executed
评论